#include "bilbao/lang/Logger.h"

namespace bilbao
{
	namespace lang
	{
		//--------------------------------------------------------------------------------
		const char* Logger::GLOBAL_NAME = "global.log";
		const char* Logger::DEBUG_LABEL = "[DEBUG]";
		const char* Logger::INFO_LABEL = "[INFO]";
		const char* Logger::NOTICE_LABEL = "[NOTICE]";
		const char* Logger::WARN_LABEL = "[WARN]";
		const char* Logger::ERROR_LABEL = "[ERROR]";
		const char* Logger::SEND_LABEL = "[SEND]";
		const char* Logger::RECEIVE_LABEL = "[RECEIVE]";
		//--------------------------------------------------------------------------------
		Logger* Logger::_instance = NULL;
		LogManager* Logger::_manager = NULL;
		//--------------------------------------------------------------------------------
		Logger::Logger( void ) :
			_name(GLOBAL_NAME)
		{
		}
		//--------------------------------------------------------------------------------
		Logger::Logger( const char* name ) :
			_name(name)
		{
		}
		//--------------------------------------------------------------------------------
		Logger::~Logger( void )
		{
			_stream.close();

			delete _manager;
			_manager = 0;

			delete _instance;
			_instance = 0;
		}
		//--------------------------------------------------------------------------------
		Logger* Logger::getLogger( void )
		{
			return getLogger(Logger::GLOBAL_NAME);
		}
		//--------------------------------------------------------------------------------
		Logger* Logger::getLogger( const char* name )
		{
			_manager = LogManager::getLogManager();

			return _manager->demandLogger(name);
		}
		//--------------------------------------------------------------------------------
		void Logger::log( PROCESSO processo, LEVEL level, const char* str )
		{
			//TODO: pegar nível de log no arquivo de parametrização
			int nivel = 1; //getNivelArquivoDeParametrização();
			int sizeFile = 0;
			int pos = 0;

			//#datahora|processo|erro/info|detalhamento
			//Abrindo aqruivo de log
			_stream.open(_name.c_str(), std::ios::app);
			sizeFile = util::BilbaoUtils::FileSize(_name);

			//Abrindo arquivo auxiliar de log, onde armazena a próxima posição onde será escrito.
			std::ofstream posFile;
			posFile.open("/home/software/log/pos.txt");
			//TODO: ler a posição do arquivo...
			//pos = readline();

			if ( nivel == 1 )
			{
				if ( (sizeFile >= (100*1024)) && (sizeFile <= (100*1024 + 5120)) ) //100Kb
				{
					//NOTE: Vai ser circular
					//TODO: Ver a função seek direitinho para apontar para a linha certa
					_stream.seekp(pos);
				}
			}
			else if ( nivel == 2 )
			{
				if ( (sizeFile >= (400*1024)) && (sizeFile <= (400*1024 + 20480)) ) //100Kb
				{
					//NOTE: Vai ser circular
					//TODO: Ver a função seek direitinho para apontar para a linha certa
					_stream.seekp(pos);
				}
			}

			if ( nivel > 0 )
			{
				//datahora
				String time("");
				util::Timing::getTimeStamp(time);
				_stream << time << "|";
				//processo
				switch ( processo )
				{
					case AC_SAT:
						_stream << "AC-SAT" << "|";
						break;
					case SAT:
						_stream << "SAT" << "|";
						break;
					case SAT_AC:
						_stream << "SAT-AC" << "|";
						break;
					case SAT_SEFAZ:
						_stream << "SAT-SEFAZ" << "|";
						break;
					case SEFAZ_SAT:
						_stream << "SEFAZ-SAT" << "|";
						break;
				}
				//erro/info
				switch ( level )
				{
					case L_INFO:
						_stream << "info" << "|";
						break;
					case L_ERROR:
						_stream << "erro" << "|";
						break;
				}
				//detalhamento + Nossa marcação...
				_stream << str << "\r\n";
			}
		}
		//--------------------------------------------------------------------------------
		void Logger::log( LEVEL level, const char* str )
		{
			time_t rawtime;
			struct tm* timeinfo;

			time ( &rawtime );
			timeinfo = localtime ( &rawtime );
			_stream.open(_name.c_str(), std::ios::app);

			_stream << asctime ( timeinfo ) << "\t";

			switch ( level )
			{
				case L_DEBUG:
					_stream << DEBUG_LABEL;
					break;
				case L_INFO:
					_stream << INFO_LABEL;
					break;
				case L_NOTICE:
					_stream << NOTICE_LABEL;
					break;
				case L_WARN:
					_stream << WARN_LABEL;
					break;
				case L_ERROR:
					_stream << ERROR_LABEL;
					break;
				case L_RECEIVE:
				case L_SEND:
					break;
			}

			_stream << "\t" << str << std::endl;
			_stream.flush();

			_stream.close();
		}
		//--------------------------------------------------------------------------------
		void Logger::log( LEVEL level, const std::stringstream& ss )
		{
			log(level, ss.str().c_str());
		}
		//--------------------------------------------------------------------------------
	}
}
